/*
 * @Description:
 * @Version: 2.0
 * @Autor: wiz
 * @Date: 2023-06-27 14:23:16
 * @LastEditors: zss
 * @LastEditTime: 2024-11-12 16:28:36
 */
import { ifs, Tsrv } from '@/services';
import { N_oSimpleToolbar } from '@/types';
import {
  CircularLayout,
  ComboForceLayout,
  ConcentricLayout,
  DagreLayout,
  ERLayout,
  ForceAtlas2Layout,
  ForceLayout,
  FruchtermanGPULayout,
  FruchtermanLayout,
  GForceGPULayout,
  GForceLayout,
  GridLayout,
  ILayout,
  MDSLayout,
  RadialLayout,
  RandomLayout
} from '@antv/layout';
import { Clipboard } from '@antv/x6-plugin-clipboard';
import { Dnd } from '@antv/x6-plugin-dnd';
import { Export } from '@antv/x6-plugin-export';
import { History } from '@antv/x6-plugin-history';
import { Keyboard } from '@antv/x6-plugin-keyboard';
import { MiniMap } from '@antv/x6-plugin-minimap';
import { Scroller } from '@antv/x6-plugin-scroller';
import { Selection } from '@antv/x6-plugin-selection';
import { Snapline } from '@antv/x6-plugin-snapline';
import { Stencil } from '@antv/x6-plugin-stencil';
import { Transform } from '@antv/x6-plugin-transform';
import { N_cFlowchart } from './types';
// import { register as regVueNode } from '@antv/x6-vue-shape';
class T_cmd {
  // 主组件箱
  private compBox: ifs.I_compBox;

  // 主组件ID
  private compID: string;

  // 主组件实例
  private self: N_cFlowchart.cFlowchart;

  private graph: N_cFlowchart.x6Graph;

  private graphConf: N_cFlowchart.I_graphOpt = null;

  // 挂载容器ID
  private graphContainer: string;

  private stdBtnList: Map<string, N_oSimpleToolbar.I_Conf> = new Map();

  private toolbarEvent: Map<string, N_cFlowchart.I_toolbarEventFun> = new Map();

  private shortcuts: Map<string, N_cFlowchart.I_shortcutsFun> = new Map();

  // 左边面板编辑节点
  private itemNodes: Set<N_cFlowchart.x6Node> = new Set();

  // 注册的节点名
  private regNodes: Set<N_cFlowchart.I_node> = new Set();

  // 注册的边名
  private regEdge: Set<N_cFlowchart.I_edge> = new Set();

  private btnUndoObj: N_oSimpleToolbar.I_Conf = null;

  private btnRedoObj: N_oSimpleToolbar.I_Conf = null;

  private _graphEditorState: N_cFlowchart.I_editorState = 'none';

  private _workMode: N_cFlowchart.I_workMode = 'view';

  public Tstencil: Stencil = null;

  public Tselection: Selection = null;

  public TminiMap: MiniMap = null;

  public Thistory: History = null;

  public Tsnapline: Snapline = null;

  public Tdnd: Dnd = null;

  public Tscroller: Scroller = null;

  public Texport: Export = null;

  public Tkeyboard: Keyboard = null;

  public Tclipboard: Clipboard = null;

  public Ttransform: Transform = null;

  // 布局对象
  private layoutObj: any = null;

  private oldGraphData: any = null;

  // 主组件created里初始化
  public init(
    self: any,
    compBoxInfo: ifs.I_compBoxInfo,
    graphContainer: string
  ) {
    this.self = self;
    this.graphContainer = graphContainer;
    this.compBox = compBoxInfo.TcompBox;
    this.compID = compBoxInfo.compID;
  }

  public get graphEditorState(): N_cFlowchart.I_editorState {
    return this._graphEditorState;
  }

  public set graphEditorState(v: N_cFlowchart.I_editorState) {
    this._graphEditorState = v;
    this.setToolbarState(v);
    this.self.$emit('graphEditorState', v);
  }

  private setToolbarState(p: N_cFlowchart.I_editorState) {
    if (this.workMode === 'view') {
      return;
    }
    switch (p) {
      case 'none':
        this.setToolbarNone();
        break;
      case 'add':
        this.setToolbarAdd();
        break;
      case 'modify':
        this.setToolbarModify();
        this.oldGraphData = Tsrv.utils.clone(this.graph.toJSON());
        break;
      case 'canEdit':
        this.setToolbarCanEdit();
        break;
      case 'noHandle':
        this.setToolbarNoHandle();
        break;
      default:
        throw new Error('setToolbarState 参数错误');
    }
  }

  private setToolbarNone() {
    this.self.showStencil = false;
    this.graph.disableSelection();
    this.stdBtnList.get('new') && (this.stdBtnList.get('new').isHide = false);
    this.stdBtnList.get('new') && (this.stdBtnList.get('new').disabled = false);
    this.stdBtnList.get('save') && (this.stdBtnList.get('save').isHide = false);
    this.stdBtnList.get('save') &&
      (this.stdBtnList.get('save').disabled = true);
    this.stdBtnList.get('saveAs') &&
      (this.stdBtnList.get('saveAs').isHide = false);
    this.stdBtnList.get('saveAs') &&
      (this.stdBtnList.get('saveAs').disabled = true);
    this.stdBtnList.get('edit') && (this.stdBtnList.get('edit').isHide = false);
    this.stdBtnList.get('edit') &&
      (this.stdBtnList.get('edit').disabled = !(
        this.graph && this.graph.getCellCount() > 0
      ));
    this.stdBtnList.get('delete') &&
      (this.stdBtnList.get('delete').isHide = false);
    this.stdBtnList.get('delete') &&
      (this.stdBtnList.get('delete').disabled = true);
    this.stdBtnList.get('cancelEdit') &&
      (this.stdBtnList.get('cancelEdit').isHide = false);
    this.stdBtnList.get('cancelEdit') &&
      (this.stdBtnList.get('cancelEdit').disabled = true);
    this.stdBtnList.get('copy') && (this.stdBtnList.get('copy').isHide = false);
    this.stdBtnList.get('copy') &&
      (this.stdBtnList.get('copy').disabled = true);
    this.stdBtnList.get('paste') &&
      (this.stdBtnList.get('paste').isHide = false);
    this.stdBtnList.get('paste') &&
      (this.stdBtnList.get('paste').disabled = true);
  }

  private setToolbarAdd() {
    this.self.showStencil = true;
    this.graph.enableSelection();
    this.stdBtnList.get('new') && (this.stdBtnList.get('new').isHide = false);
    this.stdBtnList.get('new') && (this.stdBtnList.get('new').disabled = true);
    this.stdBtnList.get('save') && (this.stdBtnList.get('save').isHide = false);
    this.stdBtnList.get('save') &&
      (this.stdBtnList.get('save').disabled = false);
    this.stdBtnList.get('saveAs') &&
      (this.stdBtnList.get('saveAs').isHide = false);
    this.stdBtnList.get('saveAs') &&
      (this.stdBtnList.get('saveAs').disabled = true);
    this.stdBtnList.get('edit') && (this.stdBtnList.get('edit').isHide = false);
    this.stdBtnList.get('edit') &&
      (this.stdBtnList.get('edit').disabled = true);
    this.stdBtnList.get('cancelEdit') &&
      (this.stdBtnList.get('cancelEdit').isHide = false);
    this.stdBtnList.get('cancelEdit') &&
      (this.stdBtnList.get('cancelEdit').disabled = true);
    this.stdBtnList.get('delete') &&
      (this.stdBtnList.get('delete').isHide = false);
    this.stdBtnList.get('delete') &&
      (this.stdBtnList.get('delete').disabled = false);
    this.stdBtnList.get('copy') && (this.stdBtnList.get('copy').isHide = false);
    this.stdBtnList.get('copy') &&
      (this.stdBtnList.get('copy').disabled = true);
    this.stdBtnList.get('paste') &&
      (this.stdBtnList.get('paste').isHide = false);
    this.stdBtnList.get('paste') &&
      (this.stdBtnList.get('paste').disabled = true);
  }

  private setToolbarModify() {
    // this.self.showStencil = true;
    this.self.setShowStencli(true);
    this.graph.enableSelection();
    this.stdBtnList.get('new') && (this.stdBtnList.get('new').isHide = false);
    // this.stdBtnList.get('new') && this.stdBtnList.get('new').disabled = true;
    this.stdBtnList.get('new') && (this.stdBtnList.get('new').disabled = false);
    this.stdBtnList.get('save') && (this.stdBtnList.get('save').isHide = false);
    this.stdBtnList.get('save') &&
      (this.stdBtnList.get('save').disabled = false);
    this.stdBtnList.get('saveAs') &&
      (this.stdBtnList.get('saveAs').isHide = false);
    this.stdBtnList.get('saveAs') &&
      (this.stdBtnList.get('saveAs').disabled = false);
    this.stdBtnList.get('edit') && (this.stdBtnList.get('edit').isHide = false);
    this.stdBtnList.get('edit') &&
      (this.stdBtnList.get('edit').disabled = true);
    this.stdBtnList.get('cancelEdit') &&
      (this.stdBtnList.get('cancelEdit').isHide = false);
    this.stdBtnList.get('cancelEdit') &&
      (this.stdBtnList.get('cancelEdit').disabled = false);
    this.stdBtnList.get('delete') &&
      (this.stdBtnList.get('delete').isHide = false);
    this.stdBtnList.get('delete') &&
      (this.stdBtnList.get('delete').disabled = true);
    this.stdBtnList.get('copy') && (this.stdBtnList.get('copy').isHide = false);
    this.stdBtnList.get('copy') &&
      (this.stdBtnList.get('copy').disabled = true);
    this.stdBtnList.get('paste') &&
      (this.stdBtnList.get('paste').isHide = false);
    this.stdBtnList.get('paste') &&
      (this.stdBtnList.get('paste').disabled = true);
  }

  private setToolbarCanEdit() {
    this.self.showStencil = false;
    this.graph.disableSelection();
    this.stdBtnList.get('new') && (this.stdBtnList.get('new').isHide = false);
    // this.stdBtnList.get('new') && this.stdBtnList.get('new').disabled = true;
    this.stdBtnList.get('new') && (this.stdBtnList.get('new').disabled = false);
    this.stdBtnList.get('save') && (this.stdBtnList.get('save').isHide = false);
    this.stdBtnList.get('save') &&
      (this.stdBtnList.get('save').disabled = true);
    this.stdBtnList.get('saveAs') &&
      (this.stdBtnList.get('saveAs').isHide = false);
    this.stdBtnList.get('saveAs') &&
      (this.stdBtnList.get('saveAs').disabled = false);
    this.stdBtnList.get('edit') && (this.stdBtnList.get('edit').isHide = false);
    this.stdBtnList.get('edit') &&
      (this.stdBtnList.get('edit').disabled = false);
    this.stdBtnList.get('cancelEdit') &&
      (this.stdBtnList.get('cancelEdit').isHide = false);
    this.stdBtnList.get('cancelEdit') &&
      (this.stdBtnList.get('cancelEdit').disabled = true);
    this.stdBtnList.get('delete') &&
      (this.stdBtnList.get('delete').isHide = false);
    this.stdBtnList.get('delete') &&
      (this.stdBtnList.get('delete').disabled = false);
    this.stdBtnList.get('copy') && (this.stdBtnList.get('copy').isHide = false);
    this.stdBtnList.get('copy') &&
      (this.stdBtnList.get('copy').disabled = true);
    this.stdBtnList.get('paste') &&
      (this.stdBtnList.get('paste').isHide = false);
    this.stdBtnList.get('paste') &&
      (this.stdBtnList.get('paste').disabled = true);
  }

  private setToolbarNoHandle() {
    this.self.showStencil = false;
    this.graph.disableSelection();
    this.stdBtnList.get('new') && (this.stdBtnList.get('new').isHide = false);
    this.stdBtnList.get('new') && (this.stdBtnList.get('new').disabled = false);
    this.stdBtnList.get('save') && (this.stdBtnList.get('save').isHide = false);
    this.stdBtnList.get('save') &&
      (this.stdBtnList.get('save').disabled = true);
    this.stdBtnList.get('saveAs') &&
      (this.stdBtnList.get('saveAs').isHide = false);
    this.stdBtnList.get('saveAs') &&
      (this.stdBtnList.get('saveAs').disabled = true);
    this.stdBtnList.get('edit') && (this.stdBtnList.get('edit').isHide = false);
    this.stdBtnList.get('edit') &&
      (this.stdBtnList.get('edit').disabled = true);
    this.stdBtnList.get('delete') &&
      (this.stdBtnList.get('delete').isHide = false);
    this.stdBtnList.get('delete') &&
      (this.stdBtnList.get('delete').disabled = true);
    this.stdBtnList.get('cancelEdit') &&
      (this.stdBtnList.get('cancelEdit').isHide = false);
    this.stdBtnList.get('cancelEdit') &&
      (this.stdBtnList.get('cancelEdit').disabled = true);
    this.stdBtnList.get('copy') && (this.stdBtnList.get('copy').isHide = false);
    this.stdBtnList.get('copy') &&
      (this.stdBtnList.get('copy').disabled = true);
    this.stdBtnList.get('paste') &&
      (this.stdBtnList.get('paste').isHide = false);
    this.stdBtnList.get('paste') &&
      (this.stdBtnList.get('paste').disabled = true);
  }

  public setBtnState(btn: string, property: string, value: boolean) {
    const find = this.self.toolbarList.find(v => v.key === btn);
    if (!Tsrv.noValue(find) && /^(disabled|isHide)$/.test(property)) {
      find[property] = value;
    }
  }

  public initstdBtnList(list: N_oSimpleToolbar.I_Conf[]) {
    list.forEach(ele => {
      this.stdBtnList.set(ele.key, ele);
    });
  }

  public get workMode(): N_cFlowchart.I_workMode {
    return this._workMode;
  }

  // 设置工作模式
  public set workMode(v: N_cFlowchart.I_workMode) {
    this._workMode = v;
    if (v === 'view') {
      this.self.showMinimap = false;
      this.self.showStencil = false;
      this.self.showContextMenu = false;
      this.setToolbarViewMode(true);
    } else if (v === 'edit') {
      this.self.showMinimap = true;
      this.self.showStencil = true;
      this.self.showContextMenu = false;
      this.setToolbarViewMode(false);
    } else {
      throw new Error('setEditorState 参数错误');
    }
  }

  private setToolbarViewMode(p: boolean) {
    this.stdBtnList.forEach((v, k) => {
      if (
        /^(open|new|edit|cancelEdit|delete|save|copy|paste|undo|redo|align|layout)$/.test(
          k
        )
      ) {
        v.isHide = p;
      }
    });
  }

  // 画布
  public setGarph(p: N_cFlowchart.x6Graph, conf: N_cFlowchart.I_graphOpt) {
    this.graph = p;
    this.graphConf = conf;
  }

  // 工具栏
  public execEvent(key: string): Promise<boolean> {
    if (this.toolbarEvent.has(key)) {
      return this.toolbarEvent.get(key)(this.self);
    }
    return Promise.resolve(true);
  }

  public regToolbarEvent(key: string, fun: N_cFlowchart.I_toolbarEventFun) {
    this.toolbarEvent.set(key, fun);
  }

  public cleanToolbarEvent() {
    this.toolbarEvent.clear();
  }

  // 快捷键
  public execShortcuts(key: string): () => boolean {
    const fn = this.shortcuts.get(key) ?? null;
    const execFun = (): boolean => {
      if (fn) {
        fn(this.self);
      }
      return false;
    };
    if (this.shortcuts.has(key)) {
      if (typeof fn === 'function') {
        return execFun;
      }
    }
    return null;
  }

  public regShortcuts(key: string, fun: N_cFlowchart.I_shortcutsFun) {
    this.shortcuts.set(key, fun);
  }

  public getShortcuts(): Map<string, N_cFlowchart.I_shortcutsFun> {
    return this.shortcuts;
  }

  public cleanShortcuts() {
    this.shortcuts.clear();
  }

  public toolbarClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    switch (cf.key) {
      case 'open':
        this.openClickHandle(cf, e);
        break;
      case 'new':
        this.newClickHandle(cf, e);
        break;
      case 'edit':
        this.editClickHandle(cf, e);
        break;
      case 'cancelEdit':
        this.cancelEditClickHandle(cf, e);
        break;
      case 'delete':
        this.deleteClickHandle(cf, e);
        break;
      case 'save':
        this.saveClickHandle(cf, e);
        break;
      case 'saveAs':
        this.saveAsClickHandle(cf, e);
        break;
      case 'copy':
        this.copyClickHandle(cf, e);
        break;
      case 'paste':
        this.pasteClickHandle(cf, e);
        break;
      case 'undo':
        this.undoClickHandle(cf, e);
        break;
      case 'redo':
        this.redoClickHandle(cf, e);
        break;
      case 'zoomIn':
        this.zoomInClickHandle(cf, e);
        break;
      case 'zoomOut':
        this.zoomOutClickHandle(cf, e);
        break;
      case 'autoZoom':
        this.autoZoomClickHandle(cf, e);
        break;
      case 'actualSize':
        this.actualSizeClickHandle(cf, e);
        break;
      case 'grid':
        this.gridClickHandle(cf, e);
        break;
      case 'align':
        this.alignClickHandle(cf, e);
        break;
      case 'nav':
        this.navClickHandle(cf, e);
        break;
      case 'layout':
        this.layoutClickHandle(cf, e);
        break;
      case 'fullScreen':
        this.fullScreenClickHandle(cf, e);
        break;
      default:
        throw new Error('未找到按钮');
    }
  }

  private openClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {}

  private newClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    this.graphEditorState = 'add';
    this.graph && this.cleanGraph();
  }

  private editClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    this.graphEditorState = 'modify';
  }

  private cancelEditClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    this.reLoadDataFromJson(JSON.stringify(this.oldGraphData));
  }

  private deleteClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    this.cleanGraph();
    this.graphEditorState = 'none';
  }

  private saveClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    this.graphEditorState = 'none';
  }

  private saveAsClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    this.graphEditorState = 'none';
  }

  private copyClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {}

  private pasteClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {}

  private undoClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    this.self.graph.undo();
  }

  private redoClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    this.self.graph.redo();
  }

  private gridClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    if (cf.isOpen) {
      this.graph.hideGrid();
      cf.isOpen = false;
    } else {
      this.graph.showGrid();
      cf.isOpen = true;
    }
  }

  private alignClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    if (cf.isOpen) {
      this.graph.disableSnapline();
      cf.isOpen = false;
    } else {
      this.graph.enableSnapline();
      cf.isOpen = true;
    }
  }

  private navClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    if (cf.isOpen) {
      this.self.showMinimap = false;
      cf.isOpen = false;
    } else {
      this.self.showMinimap = true;
      cf.isOpen = true;
    }
  }

  public layoutClickHandle(cf?: N_oSimpleToolbar.I_Conf, e?: any) {
    if (!Tsrv.noValue(this.layoutObj)) {
      const data = {
        nodes: [],
        edges: []
      };
      const cells = this.graph.getCells();
      const storeNode = new Map<string, any>();
      cells.forEach(el => {
        if (el.isNode()) {
          storeNode.set(el.id, el);
          data.nodes.push({
            id: el.id,
            size: {
              width: el.size().width,
              height: el.size().height
            }
          });
        } else if (el.isEdge()) {
          data.edges.push({
            source: el.getSourceCellId(),
            target: el.getTargetCellId()
          });
        }
      });
      this.graph.cleanClipboard();
      this.graph.cleanHistory();
      const layoutD = this.layoutObj.layout(data);
      layoutD.nodes.forEach(ele => {
        storeNode.get(ele.id).position(ele.x, ele.y);
      });
    }
  }

  private zoomInClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    this.graph.zoom(0.1);
  }

  private zoomOutClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    this.graph.zoom(-0.1);
  }

  private autoZoomClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    this.graph.zoomToFit({
      padding: 20,
      preserveAspectRatio: true
    });
  }

  private actualSizeClickHandle(cf?: N_oSimpleToolbar.I_Conf, e?: any) {
    this.graph.zoomTo(1);
  }

  private fullScreenClickHandle(cf: N_oSimpleToolbar.I_Conf, e: any) {
    this.self.isFullScreen = !this.self.isFullScreen;
    cf.class =
      this.self.isFullScreen === true ? 'wy-ios-contract' : 'wy-ios-expand';
  }

  // 设置标准按钮列表
  public setStdBtnList(list: N_oSimpleToolbar.I_Conf[]) {
    if (this.stdBtnList.size === 0) {
      list.forEach(item => {
        this.stdBtnList.set(item.key, item);
        if (item.key === 'undo') {
          this.btnUndoObj = item;
        }
        if (item.key === 'redo') {
          this.btnRedoObj = item;
        }
      });
    } else {
      list.length = 0;
      this.stdBtnList.forEach(v => {
        list.push(v);
      });
    }
  }

  public setHistoryStatus(canUndo: boolean, canRedo: boolean) {
    this.btnUndoObj && (this.btnUndoObj.disabled = !canUndo);
    this.btnRedoObj && (this.btnRedoObj.disabled = !canRedo);
  }

  public setItemNodes(nodes: N_cFlowchart.x6Node[]) {
    nodes.forEach(node => {
      this.itemNodes.add(node);
    });
  }

  public getItemNodes(): N_cFlowchart.x6Node[] {
    return Array.from(this.itemNodes);
  }

  // 记录注册的节点
  public recRegNode(node: N_cFlowchart.I_node) {
    this.regNodes.add(node);
  }

  public getRegNode(): Set<N_cFlowchart.I_node> {
    return this.regNodes;
  }

  // 记录注册的边
  public recRegEdge(edge: N_cFlowchart.I_edge) {
    this.regEdge.add(edge);
  }

  public getRegEdge(): Set<N_cFlowchart.I_edge> {
    return this.regEdge;
  }

  public setLayoutObj(layoutOpt: ILayout.LayoutOptions) {
    switch (layoutOpt.type) {
      case 'grid': // 网络布局
        this.layoutObj = new GridLayout(layoutOpt);
        break;
      case 'random': // 随机布局
        this.layoutObj = new RandomLayout(layoutOpt);
        break;
      case 'force': // 经典力导布局
        this.layoutObj = new ForceLayout(layoutOpt);
        break;
      case 'circular': // 圆形布局
        this.layoutObj = new CircularLayout(layoutOpt);
        break;
      case 'dagre': // 层次布局
        this.layoutObj = new DagreLayout(layoutOpt);
        break;
      case 'radial': // 辐射状布局
        this.layoutObj = new RadialLayout(layoutOpt);
        break;
      case 'concentric': // 同圆心布局
        this.layoutObj = new ConcentricLayout(layoutOpt);
        break;
      case 'mds': // mds 布局
        this.layoutObj = new MDSLayout(layoutOpt);
        break;
      case 'fruchterman': // fruchterman 布局
        this.layoutObj = new FruchtermanLayout(layoutOpt);
        break;
      case 'fruchterman-gpu': // fruchterman 布局
        this.layoutObj = new FruchtermanGPULayout(layoutOpt);
        break;
      case 'gForce': // graphin 中的 force 布局
        this.layoutObj = new GForceLayout(layoutOpt);
        break;
      case 'gForce-gpu': // graphin 中的 force 布局
        this.layoutObj = new GForceGPULayout(layoutOpt);
        break;
      case 'comboForce':
        this.layoutObj = new ComboForceLayout(layoutOpt);
        break;
      case 'forceAtlas2':
        this.layoutObj = new ForceAtlas2Layout(layoutOpt);
        break;
      case 'er':
        this.layoutObj = new ERLayout(layoutOpt);
        break;

      default:
        throw new Error('未知的布局类型');
    }
  }

  public getLayoutObj(): any {
    return this.layoutObj;
  }

  public defContentMenuClick(key: string) {
    switch (key) {
      case 'default:remove':
        if (!this.isDenyEdit()) {
          this.graph.removeCells(this.graph.getSelectedCells());
        }
        break;
      default:
        throw new Error('未知的菜单类型');
    }
  }

  public isDenyEdit(): boolean {
    return (
      this.graphEditorState === 'none' ||
      this.graphEditorState === 'canEdit' ||
      this.workMode === 'view'
    );
  }

  // 所有事件钩子
  public afterGraphOn = (key: string, p: N_cFlowchart.I_eventParams) => {
    if (this.isDenyEdit()) {
      return;
    }
    switch (key) {
      case N_cFlowchart.EVENTS.NODE_CONTEXTMENU: // 记录节点右键点击
        this.setSelectionByContextMenuClick(p);
        break;
      case N_cFlowchart.EVENTS.EDGE_CONTEXTMENU: // 记录边右键点击
        this.setSelectionByContextMenuClick(p);
        break;
      case N_cFlowchart.EVENTS.NODE_MOUSEENTER:
        this.nodeMouseEnter(p);
        break;
      case N_cFlowchart.EVENTS.NODE_MOUSELEAVE:
        this.nodeMouseLeave(p);
        break;
      case N_cFlowchart.EVENTS.BLANK_CLICK:
        this.blankClick(p);
        break;
      case N_cFlowchart.EVENTS.BLANK_CONTEXTMENU:
        break;
      default:
    }
  };

  private nodeMouseEnter(p?: N_cFlowchart.I_eventParams) {
    if (Tsrv.noValue(this.graph)) {
      return;
    }
    this.graph.disableHistory();
    const nodes = this.graph.getNodes();
    nodes.forEach(node => {
      const ports = node.getPorts();
      ports.forEach(port => {
        node.setPortProp(port.id, 'attrs/circle/style/visibility', 'none');
      });
    });
    this.graph.enableHistory();
  }

  private nodeMouseLeave(p?: N_cFlowchart.I_eventParams) {
    if (Tsrv.noValue(this.graph)) {
      return;
    }
    this.graph.disableHistory();
    const nodes = this.graph.getNodes();
    nodes.forEach(node => {
      const ports = node.getPorts();
      ports.forEach(port => {
        node.setPortProp(port.id, 'attrs/circle/style/visibility', 'hidden');
      });
    });
    this.graph.enableHistory();
  }

  private blankClick(p?: N_cFlowchart.I_eventParams) {
    this.graph.cleanSelection();
  }

  private setSelectionByContextMenuClick(p: N_cFlowchart.I_eventParams) {
    if (!this.graph.isSelected(p.cell)) {
      this.graph.cleanSelection();
      this.graph.select(p.cell);
    }
  }

  private cleanGraph() {
    if (this.graph) {
      this.graph.cleanClipboard();
      this.graph.cleanHistory();
      // this.graph.cleanSelection();
      // this.graph.clearTransformWidgets();
      // this.graph.clearBackground();
      // 对 clearCells 做限制修改————当清理画布时，会删除画布上的所有元素，包括节点和边，此时会触发 'cell:removed'、'node:removed' 和 'edge:removed' 事件和画布重绘。因此，在清理画布时需添加限制，避免触发上述事件。
      this.graph.clearCells({ silent: true }); // silent 为 true 时不触发 'cell:removed'、'node:removed' 和 'edge:removed' 事件和画布重绘。
    }
  }

  public reLoadDataFromJson(json: string) {
    // if (this.workMode === 'edit') {
    this.graphEditorState = 'canEdit';
    this.cleanGraph();
    this.graph.fromJSON(JSON.parse(json));

    this.graph.zoomToFit({
      padding: 20,
      preserveAspectRatio: true
    });
    // }
  }
}
interface I_cmd extends T_cmd {}

export { I_cmd, T_cmd };
